package org.ielse.frame.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import org.ielse.frame.App;
import org.ielse.frame.C;

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcelable;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;

public class BaseUtil {

	public static Map<String, String> initMap(Object... params) {
		if (params == null || params.length < 1 || params.length % 2 != 0) return null;
		Map<String, String> map = new HashMap<String, String>();
		for (int i = 0; i < params.length; i = i + 2) {
			map.put(String.valueOf(params[i]), String.valueOf(params[i + 1]));
		}
		return map;
	}

	public static Bundle initBundle(Object... params) {
		if (params == null || params.length < 1 || params.length % 2 != 0) return null;
		Bundle bundle = new Bundle();
		for (int i = 0; i < params.length; i = i + 2) {
			if (params[i + 1] instanceof String) {
				bundle.putString(String.valueOf(params[i]), String.valueOf(params[i + 1]));
			}
			else if (params[i + 1] instanceof Integer) {
				bundle.putInt(String.valueOf(params[i]), Integer.valueOf(params[i + 1].toString()));
			}
			else if (params[i + 1] instanceof Float) {
				bundle.putFloat(String.valueOf(params[i]), Float.valueOf(params[i + 1].toString()));
			}
			else if (params[i + 1] instanceof Double) {
				bundle.putDouble(String.valueOf(params[i]), Double.valueOf(params[i + 1].toString()));
			}
			else if (params[i + 1] instanceof Long) {
				bundle.putLong(String.valueOf(params[i]), Long.valueOf(params[i + 1].toString()));
			}
			else if (params[i + 1] instanceof Short) {
				bundle.putShort(String.valueOf(params[i]), Short.valueOf(params[i + 1].toString()));
			}
			else if (params[i + 1] instanceof Byte) {
				bundle.putByte(String.valueOf(params[i]), Byte.valueOf(params[i + 1].toString()));
			}
			else if (params[i + 1] instanceof Boolean) {
				bundle.putBoolean(String.valueOf(params[i]), Boolean.valueOf(params[i + 1].toString()));
			}
			else if (params[i + 1] instanceof Serializable) {
				bundle.putSerializable(String.valueOf(params[i]), (Serializable) params[i + 1]);
			}
			else if (params[i + 1] instanceof Parcelable) {
				bundle.putParcelable(String.valueOf(params[i]), (Parcelable) params[i + 1]);
			}
			else {
				throw new IllegalArgumentException("not support type");
			}
		}

		return bundle;
	}

	public static String inputStreamToString(InputStream in) {
		BufferedReader br = null;
		StringBuffer sb = new StringBuffer();
		String result = null;
		try {
			br = new BufferedReader(new InputStreamReader(in));
			String line;
			while ((line = br.readLine()) != null) {
				sb.append("\n").append(line);
			}
			if (sb.length() > 0) result = sb.substring("\n".length());
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (br != null) br.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	public static boolean inputStreamToOutputStream(InputStream input, OutputStream output) {
		BufferedInputStream in = new BufferedInputStream(input, 8 * 1024);
		BufferedOutputStream out = new BufferedOutputStream(output, 8 * 1024);
		try {
			int b;
			while ((b = in.read()) != -1) {
				out.write(b);
			}
			return true;
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (out != null) out.close();
				if (in != null) in.close();
			} catch (final IOException e) {
				e.printStackTrace();
			}
		}
		return false;
	}

	public static InputStream bitmapToInputStream(Bitmap bitmap) {
		return bytesToInputStream(bitmapToBytes(bitmap));
	}

	public static byte[] bitmapToBytes(Bitmap bitmap) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
		return baos.toByteArray();
	}

	public static InputStream bytesToInputStream(byte[] bytes) {
		return new BufferedInputStream(new ByteArrayInputStream(bytes));
	}

	public static Drawable bitmapToDrawable(Resources res, Bitmap bitmap) {
		return new BitmapDrawable(res, bitmap);
	}

	public static Bitmap drawableToBitmap(Drawable drawable) {
		Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
				drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
		Canvas canvas = new Canvas(bitmap);
		drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
		drawable.draw(canvas);
		return bitmap;
	}

	public static int dipToPx(int value) {
		DisplayMetrics dm = App.i().getResources().getDisplayMetrics();
		return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, dm);
	}

	public static int spToPx(int value) {
		DisplayMetrics dm = App.i().getResources().getDisplayMetrics();
		return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value, dm);
	}

	public static int getScreenWidth() {
		WindowManager wm = (WindowManager) App.i().getSystemService(Context.WINDOW_SERVICE);
		DisplayMetrics outMetrics = new DisplayMetrics();
		wm.getDefaultDisplay().getMetrics(outMetrics);
		return outMetrics.widthPixels;
	}

	public static int getScreenHeight() {
		WindowManager wm = (WindowManager) App.i().getSystemService(Context.WINDOW_SERVICE);
		DisplayMetrics outMetrics = new DisplayMetrics();
		wm.getDefaultDisplay().getMetrics(outMetrics);
		return outMetrics.heightPixels;
	}

	public static int getStatusBarHeight() {
		int statusHeight = -1;
		try {
			Class<?> clazz = Class.forName("com.android.internal.R$dimen");
			Object object = clazz.newInstance();
			int height = Integer.parseInt(clazz.getField("status_bar_height").get(object).toString());
			statusHeight = App.i().getResources().getDimensionPixelSize(height);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return statusHeight;
	}

	public static Bitmap screenShotWithStatusBar(Activity activity) {
		View view = activity.getWindow().getDecorView();
		view.setDrawingCacheEnabled(true);
		view.buildDrawingCache();
		Bitmap bmp = view.getDrawingCache();
		int width = getScreenWidth();
		int height = getScreenHeight();
		Bitmap bp = null;
		bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
		view.destroyDrawingCache();
		return bp;

	}

	public static Bitmap screenShotWithoutStatusBar(Activity activity) {
		View view = activity.getWindow().getDecorView();
		view.setDrawingCacheEnabled(true);
		view.buildDrawingCache();
		Bitmap bmp = view.getDrawingCache();
		Rect frame = new Rect();
		activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
		int statusBarHeight = frame.top;

		int width = getScreenWidth();
		int height = getScreenHeight();
		Bitmap bp = null;
		bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height - statusBarHeight);
		view.destroyDrawingCache();
		return bp;
	}

	public static boolean isScreenVertical(Activity context) {
		if (context == null) return true;
		int rotation = context.getWindowManager().getDefaultDisplay().getRotation();
		switch (rotation) {
		case Surface.ROTATION_90:
		case Surface.ROTATION_270:
			return false;
		}
		return true;
	}

	public static Bitmap roundImage(Bitmap resource, float roundSize) {
		final int color = 0xff424242;
		Bitmap output = Bitmap.createBitmap(resource.getWidth(), resource.getHeight(), Config.ARGB_8888);
		Canvas canvas = new Canvas(output);
		canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
		final Paint paint = new Paint();
		final Rect rect = new Rect(0, 0, resource.getWidth(), resource.getHeight());
		final RectF rectF = new RectF(rect);

		paint.setAntiAlias(true);
		paint.setColor(color);
		canvas.drawARGB(0, 0, 0, 0);
		canvas.drawRoundRect(rectF, roundSize, roundSize, paint);

		paint.setXfermode(new android.graphics.PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(resource, 0, 0, paint);
		return output;
	}

	public static Bitmap ovalImage(Bitmap resource) {
		Bitmap output = Bitmap.createBitmap(resource.getWidth(), resource.getHeight(), Config.ARGB_8888);
		Canvas canvas = new Canvas(output);
		canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
		final Paint paint = new Paint();
		final Rect rect = new Rect(0, 0, resource.getWidth(), resource.getHeight());
		final RectF rectF = new RectF(rect);

		paint.setAntiAlias(true);
		paint.setColor(0xffffffff);
		canvas.drawARGB(0, 0, 0, 0);
		canvas.drawOval(rectF, paint);

		paint.setXfermode(new android.graphics.PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(resource, 0, 0, paint);
		return output;
	}

	public static Bitmap rotateImage(Bitmap resource, final int rotateDegree) {
		Matrix matrix = new Matrix();
		matrix.setRotate(rotateDegree, (float) resource.getWidth() / 2, (float) resource.getHeight() / 2);
		try {
			return Bitmap.createBitmap(resource, 0, 0, resource.getWidth(), resource.getHeight(), matrix, true);
		} catch (OutOfMemoryError e) {
			e.printStackTrace();
		}
		return null;
	}

	public static Bitmap compressImage(Bitmap image) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		image.compress(CompressFormat.JPEG, 100, baos);
		int options = 100;
		while (baos.toByteArray().length / 1024 > 100) {
			baos.reset();
			options -= 10;
			try {
				image.compress(CompressFormat.JPEG, options, baos);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
		return BitmapFactory.decodeStream(bais, null, null);
	}

	public static void saveImageToCacheFile(final Context context, final Bitmap bmp, final String filename) {
		OutputStream stream = null;
		try {
			String savePath = context.getCacheDir().getAbsolutePath() + File.separator + filename;
			stream = new BufferedOutputStream(new FileOutputStream(savePath));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		CompressFormat format = CompressFormat.JPEG;
		int quality = 100;
		bmp.compress(format, quality, stream);
	}

	public static String saveImageToSystemAlbum(final Context context, final Bitmap bmp, final String filename) {
		OutputStream stream = null;
		try {
			File saveDirectory = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), C.settings.ALBUM_NAME);
			if (!saveDirectory.exists()) saveDirectory.mkdirs();
			File saveFile = new File(saveDirectory, filename);
			if (!saveFile.exists()) saveFile.createNewFile();
			stream = new BufferedOutputStream(new FileOutputStream(saveFile.getAbsolutePath()));
			CompressFormat format = CompressFormat.JPEG;
			int quality = 100;
			bmp.compress(format, quality, stream);
			return saveFile.getAbsolutePath();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public static Bitmap getImageFromView(View view, int width, int height) {
		int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
		int heightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
		view.measure(widthSpec, heightSpec);
		view.layout(0, 0, width, height);
		Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
		Canvas canvas = new Canvas(bitmap);
		canvas.drawColor(Color.TRANSPARENT);
		canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
		view.draw(canvas);
		return bitmap;
	}
}
